home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Collection of Tools & Utilities
/
Collection of Tools and Utilities.iso
/
dskut
/
dcache.zip
/
DCACHE.ASM
next >
Wrap
Assembly Source File
|
1988-10-11
|
55KB
|
1,036 lines
;==========================================================================
; DCACHE.COM - A fixed disk cache for the IBM Personal Computer.
; PC Magazine, Vol 7 # 17
;--------------------------------------------------------------------------
CODE SEGMENT PARA PUBLIC 'CODE'
ASSUME CS:CODE
ORG 2CH
ENV_SEG DW ? ;Segment of the environment block
ORG 80H
TAIL_LENGTH DB ? ;Length of the command tail
ORG 100H
ENTRY: JMP MAIN_ENTRY
;--------------------------------------------------------------------------
; Data Area
;--------------------------------------------------------------------------
PROGRAM DB 'DCACHE 1.0 (c) 1988 Ziff Communications Co.',13,10
DB 'PC Magazine ',254,' Douglas Boling',13,10,'$',26
ENABLED DB 1 ;0 = cache disabled, 1 = enabled
EMS_FLAG DB 0 ;use EMS ram flag, 1 = use EMS
EMS_HANDLE DW 0 ;handle for EMS memory.
ADDR_MASK DW 001EH ;Default mask set for 64K cache
SIZE_MASK DW 0
EMS_MASK DW 0 ;used to sel. the proper EMS page
DISK_NUM DB 80H ;number of fixed disk to cache
PAGE_SIZE DB 8 ;size of cache page
MAX_HEAD DW ? ;maximum value of head parameter
MAX_SECTOR DW ? ;maximum value of sector
MAX_SEGMENT DW ? ;last segment of data cache
DOSBOFFSET DW ? ;offset of dos data buffer
DOSBSEGMENT DW ? ;sector of dos data buffer
NUM_OF_SEC DB ? ;number of sectors requested
DISK_FUNCT DB ? ;function requested
SECTOR_NUM DW ? ;sector parameter from dos call
HEAD_NUM DB ? ;head parameter
CYLINDER_NUM DW ? ;cylinder parameter
SEGMENT_PTR DW 0 ;pointers into the cache
PAGE_PTR DW 0
LOG_SEC_HIGH DW 0 ;Logical sector number of disk
LOG_SEC_LOW DW 0 ; request.
LAST_BAD_PAGE DW -1 ;stores the last page that
;contained an error
LOOKUPTABLE DW OFFSET DATA_START ;offset of lookup table
CACHE_SEGMENT DW 0 ;segment of cache data
OLD_DISK_INT LABEL DWORD ;old bios interrupt 13h vector
OLD_INT13H DW 2 DUP (?)
;-----------------------------------------------------------------------------
; This routine intercepts the bios disk calls.
; Entry: ah - disk function (All other registers specific to disk read.)
; al - number of sectors es:bx - pointer to data buffer
; ch - Cylinder number dh - Head number
; cl - 7,6 Cyl. high. 5-0 sector number dl - drive number
;-----------------------------------------------------------------------------
DISK_INT PROC FAR
ASSUME CS:CODE,DS:NOTHING,ES:NOTHING
CMP CS:ENABLED,0 ;See if cache enabled
JE SKIP_CACHE
CMP DL,CS:DISK_NUM ;See if the correct disk
JNE SKIP_CACHE
STI ;Allow interrupts
CMP AH,2 ;If any other function besides
JE CACHE_IT ; read or write, reset cache.
CMP AH,3
JE CACHE_IT1
CMP AH,1 ;If just checking the last status
JE SKIP_CACHE ; skip cache, but don't reset.
RESET_CMD:
PUSH ES ;If the command is not a simple
PUSH CS ; read, write, or status, assume
POP ES ; the worst and clear the lookup
ASSUME ES:CODE ; table.
CALL RESET_CACHE
POP ES
ASSUME ES:NOTHING
SKIP_CACHE:
JMP CS:OLD_DISK_INT ;jmp to bios disk routine.
;--------------------------------------------------------------------------
;Compute the logical sector number from the cylinder, head, and sector.
;--------------------------------------------------------------------------
CACHE_IT:
CMP AL,CS:PAGE_SIZE ;For disk read, cache reads of
JA SKIP_CACHE ; a page or less.
CACHE_IT1:
PUSH DS ;save registers
PUSH DI
PUSH SI
PUSHF
PUSH AX
PUSH BX
PUSH CX
PUSH DX
PUSH CS ;set ds to code segment
POP DS
ASSUME DS:CODE
;--------------------------------------------------------------------------
;Store calling parameters.
;--------------------------------------------------------------------------
MOV DOSBOFFSET,BX ;save dos pointer to its data
MOV DOSBSEGMENT,ES ; buffer.
MOV BX,CX ;copy cx
AND BX,003FH ;strip all but the sector number
MOV SECTOR_NUM,BX ;save sector number
MOV HEAD_NUM,DH ;save head number
MOV NUM_OF_SEC,AL ;save the number of sectors needed
MOV DISK_FUNCT,AH ;save function called.
;--------------------------------------------------------------------------
;Compute logical sector number from the cylinder, head, and sector parameters.
;--------------------------------------------------------------------------
XCHG CL,CH ;create full 10 bit cylinder num.
ROL CH,1 ; the top 2 bits are in ch bits
ROL CH,1 ; 7 and 6. roll them into bits
AND CH,03H ; 1 and 2.
MOV CYLINDER_NUM,CX ;save the cylinder number
MOV AX,CX ;copy cylinder number for multiply
MOV BL,DH ;get head number out of dx
MUL MAX_HEAD ;multiply cylinder to make room
XOR BH,BH ;clear high byte of head value
ADD AX,BX ;add in head.
MUL MAX_SECTOR ;multiply by max sector value
ADD AX,SECTOR_NUM ;add sector number
ADC DX,0 ;propigate carry.
MOV LOG_SEC_HIGH,DX ;save logical sector number
MOV LOG_SEC_LOW,AX
;--------------------------------------------------------------------------
;Store values needed later.
;--------------------------------------------------------------------------
MOV BH,AL
SHL BH,1
AND BX,3E00H
MOV PAGE_PTR,BX ;save page index
AND BH,30H
MOV SI,BX ;save page index for cache load
;--------------------------------------------------------------------------
;Point the segment register to the proper DOS memory block
;--------------------------------------------------------------------------
MOV BX,AX ;copy logical sector low
MOV CL,5
SHL BX,CL ;Convert logical sector number to
AND BX,SIZE_MASK ; cache page index
ADD BX,CACHE_SEGMENT
MOV SEGMENT_PTR,BX ;save segment